package com.tianji.learning.service.impl;

import com.tianji.api.client.course.CourseClient;
import com.tianji.api.dto.course.CourseFullInfoDTO;
import com.tianji.api.dto.leanring.LearningLessonDTO;
import com.tianji.api.dto.leanring.LearningRecordDTO;
import com.tianji.common.exceptions.BizIllegalException;
import com.tianji.common.exceptions.DbException;
import com.tianji.common.utils.BeanUtils;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.domain.dto.LearningRecordFormDTO;
import com.tianji.learning.domain.po.LearningLesson;
import com.tianji.learning.domain.po.LearningRecord;
import com.tianji.learning.enums.LessonStatus;
import com.tianji.learning.enums.SectionType;
import com.tianji.learning.mapper.LearningRecordMapper;
import com.tianji.learning.service.ILearningLessonService;
import com.tianji.learning.service.ILearningRecordService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tianji.learning.utils.LearningRecordDelayTaskHandler;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * <p>
 * 学习记录表 服务实现类
 * </p>
 *
 * @author Yandel
 * @since 2025-05-01
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class LearningRecordServiceImpl extends ServiceImpl<LearningRecordMapper, LearningRecord> implements ILearningRecordService {

    private final ILearningLessonService lessonService;
    private final CourseClient courseClient;

    private final LearningRecordDelayTaskHandler taskHandler;

    @Override
    public LearningLessonDTO queryLearningRecordByCourse(Long courseId) {

        //1.获取用户id
        Long userId = UserContext.getUser();
        //2.查询课表信息
        // SELECT id,user_id,course_id,status,week_freq,plan_status,learned_sections,latest_section_id,
        // latest_learn_time,create_time,expire_time,update_time FROM learning_lesson WHERE (user_id = ? AND course_id = ?)
        LearningLesson lesson = lessonService.lambdaQuery()
                .eq(LearningLesson::getUserId, userId)
                .eq(LearningLesson::getCourseId, courseId)
                .one();
        if (lesson == null) {
            throw new BizIllegalException("用户没有该课程的记录");
        }
        //3.查询学习记录
        // SELECT id,lesson_id,section_id,user_id,moment,finished,create_time,finish_time,
        // update_time FROM learning_record WHERE (user_id = ? AND lesson_id = ?)
        List<LearningRecord> recordList = this.lambdaQuery()
                .eq(LearningRecord::getUserId, userId)
                .eq(LearningRecord::getLessonId, lesson.getId())
                .list();
        //4.封装结果返回
        LearningLessonDTO dto = new LearningLessonDTO();
        dto.setId(lesson.getId());
        dto.setLatestSectionId(lesson.getLatestSectionId());//最近学习的小节id
        //BeanUtils拷贝，LearningRecord -> LearningRecordDTO
        List<LearningRecordDTO> copiedList = BeanUtils.copyList(recordList, LearningRecordDTO.class);
        dto.setRecords(copiedList);//LearningRecordDTO  型的集合

        return dto;
    }

    @Override
    public void addLearningRecord(LearningRecordFormDTO recordDTO) {
        //1.获取登录用户id
        Long userId = UserContext.getUser();
        //2.处理学习记录
        boolean isFinished = false;//代表本小节是否第一次学完
        if (recordDTO.getSectionType() == SectionType.VIDEO) {
            // 2.1.处理视频
            isFinished = handleVideoRecord(userId, recordDTO);
        } else {
            // 2.2.处理考试
            isFinished = handleExamRecord(userId, recordDTO);
        }
        //3.处理课表数据
        if (!isFinished){
            return;
        }
        handleLearningLessonChanges(recordDTO);
    }

    private void handleLearningLessonChanges(LearningRecordFormDTO recordDTO) {
        //1.查询课程表 learning_lesson   查询条件 lesson_id 主键
        LearningLesson lesson = lessonService.getById(recordDTO.getLessonId());
        if (lesson == null) {
            throw new BizIllegalException("课表不存在");
        }
        //2. 判断是否是第一次学完    isFinished 为true表示第一次学完
        boolean allFinished = false;//所有小节数是否学完

            //3.远程调用课程服务，得到课程信息   小节总数
            CourseFullInfoDTO cinfo = courseClient.getCourseInfoById(lesson.getCourseId(), false, false);
            if (cinfo == null) {
                throw new BizIllegalException("课程不存在");
            }
            Integer sectionNum = cinfo.getSectionNum();//该课程下的小节总数

            //4.如果isFinished为true 本小节是第一次学完  判断该用户对该课程下的小节是否全部学完
            Integer learnedSections = lesson.getLearnedSections();//已学过的小节数量
            allFinished = learnedSections + 1 >= sectionNum;


        //5.更新课表数据
        boolean result = lessonService.lambdaUpdate()
//                .set(lesson.getStatus()==LessonStatus.NOT_BEGIN,  LearningLesson::getStatus, LessonStatus.LEARNING)
                //如果该课表状态为未开始，则更新为学习中
                .set(lesson.getLearnedSections() == 0, LearningLesson::getStatus, LessonStatus.LEARNING.getValue())
                .set(allFinished, LearningLesson::getStatus, LessonStatus.FINISHED)
                .set(LearningLesson::getLatestSectionId, recordDTO.getSectionId())
                .set(LearningLesson::getLatestLearnTime, recordDTO.getCommitTime())
//                .set(isFinished, LearningLesson::getLearnedSections,lesson.getLearnedSections()+1)
                //如果已学完，则小节数加1
                .setSql( "learned_sections = learned_sections + 1")
                .eq(LearningLesson::getId, lesson.getId())
                .update();
        if (!result) {
            throw new DbException("更新课表数据失败");
        }

    }

    //处理视频播放记录
    private boolean handleVideoRecord(Long userId, LearningRecordFormDTO recordDTO) {
        //1.查询旧的考试记录 learning_record  查询条件 user_id, lesson_id
        LearningRecord learningRecord = queryOldRecord(recordDTO.getLessonId(), recordDTO.getSectionId());
//        LearningRecord learningRecord = this.lambdaQuery()
//                .eq(LearningRecord::getUserId, userId)
//                .eq(LearningRecord::getLessonId, recordDTO.getLessonId())
//                .eq(LearningRecord::getSectionId, recordDTO.getSectionId())
//                .one();
        //2.判断是否存在
        if (learningRecord == null) {
            //3.不存在则新增学习记录
            LearningRecord record = BeanUtils.copyBean(recordDTO, LearningRecord.class);
            record.setUserId(userId);
            boolean result = this.save(record);
            if (!result) {
                throw new DbException("新增考试记录失败");
            }
            return false;//代表本小节没有学完
        }
        //4、如果存在则更新学习记录 learning_record 更新字段 moment, finished, finish_time
        //判断本小节是否是第一次学完
        // isFinished 为true表示第一次学完
        boolean isFinished = !learningRecord.getFinished() && recordDTO.getMoment() * 2 >= recordDTO.getDuration();
        if (!isFinished) {
            LearningRecord record = new LearningRecord();
            record.setLessonId(recordDTO.getLessonId());
            record.setSectionId(recordDTO.getSectionId());
            record.setMoment(recordDTO.getMoment());
            record.setFinished(learningRecord.getFinished());
            record.setId(learningRecord.getId());
            taskHandler.addLearningRecordTask(record);
            return false;
        }

        boolean result = this.lambdaUpdate()
                .set(LearningRecord::getMoment, recordDTO.getMoment())
                .set(isFinished, LearningRecord::getFinished, true)
                .set(isFinished, LearningRecord::getFinishTime, recordDTO.getCommitTime())
                .eq(LearningRecord::getId, learningRecord.getId())
                .update();
        if (!result) {
            throw new DbException("更新视频学习记录失败");
        }

        //清除redis缓存
        taskHandler.cleanRecordCache(recordDTO.getLessonId(), recordDTO.getSectionId());
        return true;
    }

    private LearningRecord queryOldRecord(Long lessonId, Long sectionId) {
        //1.查询缓存
        LearningRecord cache = taskHandler.readRecordCache(lessonId, sectionId);
        //2.如果名中直接返回
        if (cache != null) {
            return cache;
        }
        //3.未命中  查询db
        LearningRecord DbRecord = this.lambdaQuery()
                .eq(LearningRecord::getLessonId, lessonId)
                .eq(LearningRecord::getSectionId, sectionId)
                .one();
        if (DbRecord == null) {//不写可能会报空指针异常
            return null;
        }
        //4.存入缓存
        taskHandler.writeRecordCache(DbRecord);
        return DbRecord;
    }

    //处理考试记录
    private boolean handleExamRecord(Long userId, LearningRecordFormDTO recordDTO) {

        //1.1 将dto转换po    (po相当于实体类中的entity)
        LearningRecord record = BeanUtils.copyBean(recordDTO, LearningRecord.class);
        record.setUserId(userId);
        record.setFinished(true);//提交考试记录，表示本节已学完
        record.setCreateTime(recordDTO.getCommitTime());

        //2.保存学习记录 learning_record
        boolean result = this.save(record);
        if (!result) {
            throw new DbException("保存学习记录失败");
        }
        return true;
    }

}
